home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / program / p063b9s.zip / UNIT / YOOHOO2U.PAS < prev    next >
Pascal/Delphi Source File  |  1997-03-02  |  38KB  |  1,247 lines

  1. UNIT YooHoo2U;
  2. {╔══════════════════════════════════════════════════════════════════════════╗}
  3. {║ YooHoo/2U2 & EMSI protocol routines           Last changed: 02.03.97  SA ║}
  4. {║                                                                          ║}
  5. {║                         (C) Copyright 1989-97 by                         ║}
  6. {║       Dan Wulff, Jens Sandalgaard, Steen Christensen & S¢ren Ager        ║}
  7. {║                                                                          ║}
  8. {║ This source may not be given to anybody, without the written permission  ║}
  9. {║ from The Portal Team.                                                    ║}
  10. {╚══════════════════════════════════════════════════════════════════════════╝}
  11. {$I POPDEFS.INC}
  12.  
  13. INTERFACE
  14.  
  15. USES Use32;
  16.  
  17. FUNCTION  StartMailSession: Boolean;
  18. PROCEDURE ReceiveMailSession(InByte: Integer);
  19.  
  20. IMPLEMENTATION
  21.  
  22. USES OpCrt, OpWindow, OpString, OpDos, OpDate, Dos, ApTimer,
  23.      Globals, Com, Crc, Modem, NodeList, MailUtil, WZSend, UnixDate,
  24.      ZMisc, ZSend, ZReceive, OproUtil, Display, Util, BiMail, StrUtil,
  25.      FileUtil, Protocol, FallBack, Janus, TransVid, LogFile, DosShell, InterCom,
  26.      MTask, ParseReq, NetFile, PoPTypes;
  27.  
  28. CONST
  29.   EMSIBufLen = 4096;
  30.  
  31. TYPE
  32.   TEMSIData = RECORD
  33.     BaudRate,
  34.     Options    : S20;
  35.     Flags,
  36.     ProdSerial,
  37.     ProdName,
  38.     Location,
  39.     Phone      : S80;
  40.     Tranx      : S8;
  41.   END;
  42.  
  43.   EMSIBufType=ARRAY[1..EMSIBufLen] OF CHAR;
  44.  
  45. VAR
  46.   AkaNum         : ShortInt;
  47.   EMSIData       : TEMSIData;
  48.  
  49.   FUNCTION NowAsUnixDate: LongInt;
  50.   VAR
  51.     d,m,y,dow,h,min,s,s100 : Word;
  52.   BEGIN
  53.     GetDate(y,m,d,dow);
  54.     GetTime(h,min,s,s100);
  55.     NowAsUnixDate:=GetUnixDate(y,m,d,h,min,s);
  56.   END;
  57.  
  58.   PROCEDURE RemoveEmptyDir(CONST Adr: TFidoAddress);
  59.   VAR
  60.     s : PathStr;
  61.   BEGIN
  62.     IF NOT Cfg.KeepEmptyDirs THEN
  63.     BEGIN
  64.       ChangeDir(Cfg.Outbound);
  65.       IF Adr.Point<>0 THEN
  66.       BEGIN
  67.         s:=HoldAreaPath(Adr,False);
  68.         RmDir(Copy(s,1,Length(s)-1));
  69.         IF IOResult<>0 THEN ;
  70.       END;
  71.       IF Adr.Zone<>Cfg.Addresses[Cfg.MainAdrNum].Zone THEN
  72.       BEGIN
  73.         s:=HoldAreaNameMunge(Adr.Zone,False);
  74.         RmDir(Copy(s,1,Length(s)-1));
  75.         IF IOResult<>0 THEN ;
  76.       END;
  77.       ChDir(Copy(StartPath, 1, Length(StartPath)-1));
  78.     END;
  79.   END;
  80.  
  81.   PROCEDURE GetRightAkA(VAR Address: TFidoAddress; VAR AkaNum: ShortInt);
  82.   VAR
  83.     i : Byte;
  84.     Found : Boolean;
  85.   BEGIN
  86.     Address:=Cfg.Addresses[Cfg.MainAdrNum];
  87.     i:=1 ; Found:=False ;
  88.     AkaNum:=Cfg.MainAdrNum;
  89.     REPEAT
  90.       IF (Cfg.Addresses[i].Zone<>0) And (Cfg.Addresses[i].Zone=Call.Zone) AND
  91.          (Cfg.Addresses[i].Zone<>Cfg.Addresses[Cfg.MainAdrNum].Zone) THEN
  92.       BEGIN
  93.         Address:=Cfg.Addresses[i];
  94.         AddLog(':','Using AKA: ('+Address2Str(Address)+')');
  95.         Found:=True;
  96.         AkaNum:=i;
  97.       END;
  98.       Inc(i);
  99.     UNTIL (i>MaxAddresses) OR (Found);
  100.   END;
  101.  
  102.   FUNCTION CheckPassword(HaveBoth: Boolean): Boolean;
  103.   VAR
  104.     Node : TNodeInfo;
  105.     f    : TNetFile;
  106.   BEGIN
  107.     CheckPassword:=True;
  108.     IF AsciiZ2Str(Hello.Password,8)<>'' THEN
  109.     BEGIN
  110.       IF HaveBoth And (StUpCase(AsciiZ2Str(Hello.Password,8))<>Trim(StUpCase(AsciiZ2Str(RemHello.Password,8)))) THEN
  111.       BEGIN
  112.         IF IsCaller THEN
  113.         BEGIN
  114.           AddLog('!','Password override on outgoing call: (local/remote) "'
  115.                      +StUpCase(AsciiZ2Str(Hello.Password,8))+'"/"'+Trim(StUpCase(AsciiZ2Str(RemHello.Password,8)))+'"');
  116.         END ELSE
  117.         BEGIN
  118.           AddLog('!', 'Password error: (local/remote) "'+
  119.                       +StUpCase(AsciiZ2Str(Hello.Password,8))+'"/"'+Trim(StUpCase(AsciiZ2Str(RemHello.Password,8)))+'"');
  120.           DropCarrier;
  121.           CheckPassword:=False;
  122.         END;
  123.       END;
  124.     END ELSE
  125.       IF (HaveBoth) AND (RemHello.PassWord[1]<>#0) THEN
  126.       BEGIN
  127.         AddLog('#','Remote has password on you: "'+StUpCase(AsciiZ2Str(RemHello.Password,8))+'"');
  128.  
  129. { Check på en eller anden liste over adresser der må oprettes }
  130.         IF FindNodeInfo(Node, RemHello.Address) THEN
  131.           AddLog(':','Updating password for '+Address2Str(RemHello.Address))
  132.         ELSE
  133.           AddLog(':','Added '+Address2Str(RemHello.Address)+' to nodes');
  134.         Node.SessionPwd:=StUpCase(AsciiZ2Str(RemHello.Password,8));
  135.         Node.Address:=RemHello.Address;
  136.         PutNodeInfo(Node);
  137. {
  138.           f.Open(StartPath+PoPNodesFileName, SizeOf(Node), True) ;
  139.           f.Seek(f.RecNum+1);
  140.           f.Write(Node);
  141.           f.Close;
  142.         END
  143. }
  144.       END;
  145.   END;
  146.  
  147.   PROCEDURE FillOutHello;
  148.   VAR
  149.     ok: Integer;
  150.   BEGIN
  151.     FillChar(Hello, SizeOf(Hello), 0);
  152.     WITH Hello DO
  153.     BEGIN
  154.       Signal:=$6f;
  155.       HelloVersion:=$01;
  156.       ProductCode:=PoPProductCode;
  157.       Val(Copy(Ver,1,Pos('.',Ver)-1),ProductMaj,ok);
  158.       Val(Copy(Ver,Pos('.',Ver)+1,2),ProductMin,ok);
  159.       Str2AsciiZ(cfg.system, SystemName, 60);
  160.       Str2AsciiZ(cfg.sysop, Sysop, 20);
  161.       Address.Zone:=Cfg.Addresses[Cfg.MainAdrNum].Zone;
  162.       IF (Not IsCaller) Or (NodesRec.UseFake=#0) THEN NodesRec.UseFake:=' ';
  163.       IF (Cfg.Addresses[Cfg.MainAdrNum].Point<>0) And
  164.          (((Cfg.UseFakeAddress) And (NodesRec.UseFake=' ')) Or
  165.          (NodesRec.UseFake='Y')) THEN
  166.       BEGIN
  167.         Address.Net:=Cfg.Pointnet;
  168.         Address.Node:=Cfg.Addresses[Cfg.MainAdrNum].Point;
  169.       END ELSE
  170.       BEGIN
  171.         Address:=Cfg.Addresses[Cfg.MainAdrNum];
  172.         GetRightAkA(Address,AkaNum);
  173.       END;
  174.       IF FoundInNodes AND (NodesRec.SessionPwd<>'') THEN
  175.         Str2AsciiZ(NodesRec.SessionPwd, Password, 9)
  176.       ELSE
  177.         IF FoundInNl THEN Str2AsciiZ(NodelistEntry.Password, Password, 9);
  178.       Capabilities:=[ZedZapper, ZedZipper];
  179.       IF ((CurrentEvent.typ AND etRequests)=etRequests) AND (ReqOk) AND
  180.          NOT (NodesRec.DisallowReq) AND (ComPort^.GetBaudRate>=Cfg.Request.MinBaud) THEN Capabilities:=Capabilities + [WzFreq];
  181.       IF FullDuplex THEN
  182.       BEGIN
  183. {$IFNDEF OS2}
  184.         IF (Cfg.Bimail.BimodemPath<>'') And (NodesRec.UseFullDuplex IN [#0,'Y','B',' ']) THEN
  185.           Capabilities:=Capabilities + [CanDoBiMail];
  186. {$ENDIF}
  187.         IF ((Cfg.UseJanus) And (NodesRec.UseFullDuplex IN [#0,'Y','J',' '])) Or
  188.            (NodesRec.UseFullDuplex IN ['Y','J']) THEN
  189.           Capabilities:=Capabilities + [DoesJanus];
  190.       END;
  191.     END;
  192.   END;
  193.  
  194.   PROCEDURE ShowHisData;
  195.   VAR
  196.     TmpPtr : POutList;
  197.     s : String;
  198.     i : Byte;
  199.     l : LongInt;
  200.     d, m, y, h, min, sec : Word;
  201.   BEGIN
  202.     IF RemHello.ProductCode=PoPProductCode THEN
  203.       IntroWin^.wFastWrite('PoP²', 2, 76, Cfg.Color[1].TextColor OR Blink);
  204.     GotSomeMail:=False;
  205.     GotSomeFiles:=False;
  206.     IF Not CmpAdr(Call, RemHello.Address) AND (IsCaller) THEN
  207.     BEGIN
  208.       AddLog(':','Called '+Address2Str(Call)+' and got '+Address2Str(RemHello.Address));
  209.       i:=1;
  210.       WHILE (i<=MaxAddresses) AND (RemAka[i].Zone<>0) DO
  211.         Inc(i);
  212.       IF i<=MaxAddresses THEN RemAka[i]:=RemHello.Address;
  213.     END;
  214.     IF NOT IsCaller THEN
  215.     BEGIN
  216.       Call:=RemHello.Address;
  217.       RemapAddress(Call);
  218.       IF RemHello.SystemName[1]=#0 THEN
  219.         IF FoundInNl THEN
  220.         BEGIN
  221.           Move(NodelistEntry.SystemName[1], RemHello.SystemName, Length(NodelistEntry.SystemName));
  222.           Move(NodelistEntry.SysOpName[1], RemHello.SysOp, Length(NodelistEntry.SysOpName));
  223.         END ELSE
  224.         BEGIN
  225.           s:='Unknown';
  226.           Move(s[1], RemHello.SystemName, Length(s));
  227.           Move(s[1], RemHello.SysOp, Length(s));
  228.         END;
  229.       SetInterCom(ICConnect,Call,False);
  230.     END;
  231.     IntroWin^.wFastText(Pad(Copy(Asciiz2Str(RemHello.SystemName, 60),1,45)+' - '+Asciiz2Str(RemHello.sysop,20)+
  232.                         ' ('+Address2Str(RemHello.Address)+')', 79),1,2);
  233.     IF IsCaller THEN
  234.       AddToCallList(2,RemHello.Address,AsciiZ2Str(RemHello.SystemName,60))
  235.     ELSE
  236.       AddToCallList(1,RemHello.Address,AsciiZ2Str(RemHello.SystemName,60));
  237.     AddLog('*', Asciiz2Str(RemHello.SystemName, 60)+' ('+Address2Str(RemHello.Address)+')');
  238.     AddLog('*','Remote uses: ' + ProductNames(RemHello.ProductCode)+' Version '+Long2Str(RemHello.ProductMaj)+'.'+
  239.                   tochar(RemHello.ProductMin));
  240.     AddLog(':', 'SysOp: ' + Asciiz2Str(RemHello.sysop, 20));
  241.     IF RemHello.Password[1] <> #0 THEN
  242.       AddLog('*', 'Password protected session');
  243.     IF RemAka[1].Zone<>0 THEN
  244.     BEGIN
  245.       s:='Remote AKA''s:';
  246.       i:=1;
  247.       WHILE (i<=MaxAddresses) AND (RemAka[i].Zone<>0) DO
  248.       BEGIN
  249.         s:=s+' '+Address2Str(RemAka[i]);
  250.         Inc(i);
  251.       END;
  252.       AddLog(':',s)
  253.     END;
  254.     IF EMSIData.Phone<>'' THEN      AddLog(':','EMSI Phone       : '+EMSIData.Phone);
  255.     IF EMSIData.Location<>'' THEN   AddLog(':','EMSI Location    : '+EMSIData.Location);
  256.     IF EMSIData.Options<>'' THEN    AddLog(':','EMSI Options     : '+EMSIData.Options);
  257.     IF EMSIData.Flags<>'' THEN      AddLog(':','EMSI Flags       : '+EMSIData.Flags);
  258.     IF EMSIData.BaudRate<>'' THEN   AddLog(':','EMSI Baudrate    : '+EMSIData.BaudRate);
  259.     IF EMSIData.ProdName<>'' THEN   AddLog('*','EMSI Product name: '+EMSIData.ProdName);
  260.     IF EMSIData.ProdSerial<>'' THEN AddLog('*','EMSI serial no.  : '+EMSIData.ProdSerial);
  261.     IF EMSIData.Tranx<>'' THEN
  262.     BEGIN
  263.       IF Str2Long('$'+EMSIData.Tranx, l) THEN
  264.       BEGIN
  265.          UnpackUnix(l, y, m, d, h, min, sec);
  266.          AddLog('*','EMSI Tranx time  : '+DMYToDateString('dd nnn yy', d, m, y)+'  '+
  267.                                           TimeToTimeString('hh:mm:ss', HMSToTime(h, min, sec)));
  268.         IF NodesRec.EMSISetTime THEN SynchTimeDiff:=l-NowAsUnixDate+1;
  269.       END;
  270.     END;
  271.     IF NOT IsCaller THEN
  272.     BEGIN
  273.       IF (Pos('PUP',EMSIData.Options)>0) or (Pos('NPU',EMSIData.Options)>0) THEN RemAka[1].Zone:=0;
  274.       TmpPtr:=POutList(OutList^.Head);
  275.       WHILE (TmpPtr<>Nil) And Not CmpAdr(Call, TmpPtr^.Address) DO
  276.         TmpPtr:=POutList(OutList^.Next(TmpPtr));
  277.       IF TmpPtr<>Nil THEN
  278.       BEGIN
  279.         CLOutListPtr:=TmpPtr; FLOutListPtr:=TmpPtr;
  280.         UpdateOutboundWindow;
  281.       END;
  282.       IF (CurrentEvent.ConnectTo.Zone<>0) AND
  283.          (NOT TimeIsBetween(Cfg.ZMHStart,Cfg.ZMHEnd)) AND
  284.          (NOT CmpAdr(CurrentEvent.ConnectTo,RemHello.Address)) THEN
  285.       BEGIN
  286.         AddLog('!','Only '+Address2Str(CurrentEvent.ConnectTo)+' allowed. Hanging up');
  287.         DropCarrier;
  288.       END;
  289.       IF (GlobNodeStat=nsUnKnown) AND Cfg.Curmudgeon THEN
  290.       BEGIN
  291.         AddLog('!','Only known system allowed. Hanging up');
  292.         DropCarrier;
  293.       END;
  294.     END;
  295.   END;
  296.  
  297.   FUNCTION SendHello : Boolean;
  298.   LABEL h2;
  299.   VAR
  300.     t1,
  301.     FailSafe : EventTimer;
  302.     InByte   : Integer;
  303.     Crc16    : Word;
  304.     a        : Byte;
  305.   BEGIN
  306.     SendHello:=False;
  307.     FillOutHello;
  308.     IF Not CheckPassword(Not IsCaller) THEN
  309.     BEGIN
  310.       DropCarrier;
  311.       Exit;
  312.     END;
  313.     ComPort^.SetXon(off);
  314.     ComPort^.SetBreak(Off);
  315. {   IF FCtrlC(0) THEN ;}
  316.     NewTimerSecs(FailSafe, 60);
  317.     REPEAT
  318. h2:
  319.       ComPort^.WriteByte($1f, False);
  320.       Crc16:=0;
  321.       FOR a:=1 TO 128 DO
  322.       BEGIN
  323.         ComPort^.WriteByte(HelloByte[a], False);
  324.         Crc16:=UpdCrc16(HelloByte[a], Crc16);
  325.       END;
  326.       IF NOT ComPort^.Carrier THEN Exit;
  327.       Crc16:=UpdCrc16(0, Crc16);
  328.       Crc16:=UpdCrc16(0, Crc16);
  329.       ComPort^.PurgeIn;
  330.       ComPort^.WriteByte(Hi(Crc16), False);
  331.       ComPort^.WriteByte(Lo(Crc16), True);
  332.       NewTimerSecs(t1, 30);
  333.       REPEAT
  334.         InByte:=TimedRead(1000);
  335.         IF InByte<0 THEN
  336.         BEGIN
  337.           AddLog('!', 'SendHello: TimeOut'); { = timed out }
  338.           DropCarrier;
  339.           Exit;
  340.         END;
  341.         CASE InByte OF
  342.           Ack: BEGIN
  343.                  SendHello:=True;
  344.                  EXIT;
  345.                END;
  346.           63 : BEGIN
  347.                  AddLog('!', 'drats');
  348.                  GOTO h2;
  349.                END;
  350.         END;
  351.       UNTIL TimerExpired(t1);
  352.     UNTIL TimerExpired(FailSafe);
  353.   END;
  354.  
  355.   FUNCTION GetHello : Boolean;
  356.   LABEL r2,r3,r4,r5,r6,r7,r8;
  357.   VAR
  358.     FailSafe       : EventTimer;
  359.     InByte         : Integer;
  360.     a,count,errors : Byte;
  361.     CrcIn, Crc16   : Word;
  362.   BEGIN
  363.     GetHello:=False;
  364.     ComPort^.PurgeIn;
  365.     ComPort^.PurgeOut;
  366.     FillChar(RemHello, SizeOf(RemHello), 0);
  367.     ComPort^.SetXon(off);
  368.     ComPort^.SetBreak(Off);
  369. {   IF FCtrlC(0) THEN ;}
  370.     count:=0;
  371.     errors:=0;
  372.     NewTimerSecs(FailSafe, 30);
  373. r2:
  374.     ComPort^.WriteByte(Enq, True);
  375. r3:
  376.     InByte:=TimedRead(100);
  377.     IF InByte<0 THEN GOTO r4;
  378.     IF NOT ComPort^.Carrier THEN EXIT;
  379.     CASE InByte OF
  380.       $1f    : GOTO r5;
  381.       YooHoo : GOTO r2;
  382.       ELSE     GOTO r3;
  383.     END;
  384. r4:
  385.     Inc(Count);
  386.     IF Count>9 THEN Exit ELSE GOTO r2;
  387. r5:
  388.     { Get hello packet from other end }
  389.     Crc16:=0;
  390.     FOR a:=1 TO 128 DO
  391.     BEGIN
  392.       InByte:=TimedRead(1000);
  393.       IF (InByte<0) OR (TimerExpired(FailSafe)) THEN Exit;
  394.       RemHelloByte[a]:=LO(InByte);
  395.       Crc16:=UpdCrc16(RemHelloByte[a], Crc16);
  396.     END;
  397. r6:
  398.     Crc16:=UpdCrc16(0, Crc16);
  399.     Crc16:=UpdCrc16(0, Crc16);
  400.     InByte:=TimedRead(1000);
  401.     IF NOT ComPort^.Carrier THEN Exit;
  402.     IF InByte<0 THEN GOTO r7;
  403.     CrcIn:=WORD(LO(InByte) SHL 8);
  404.     InByte:=TimedRead(1000);
  405.     IF NOT ComPort^.Carrier THEN Exit;
  406.     IF InByte<0 THEN GOTO r7;
  407.     CrcIn:=CrcIn + LO(InByte);
  408.     IF CrcIn=Crc16 THEN GOTO r8 ELSE GOTO r7;
  409. r7:
  410.     Inc(Errors);
  411.     IF errors>9 THEN EXIT;
  412.     ComPort^.WriteByte(Byte('?'), True);
  413.     GOTO r3;
  414. r8:
  415.     ComPort^.WriteByte(Byte(Ack), False);
  416.     ComPort^.WriteByte(Byte(YooHoo), True);
  417.     ShowHisData;
  418.     GetHello:=ComPort^.Carrier;
  419.   END;
  420.  
  421.   FUNCTION WaZoo: Boolean;
  422.   LABEL
  423.     ItsOverAndOut;
  424.   VAR
  425.     SaveDir,
  426.     ReqFile : PathStr;
  427.     SaveWin : Pointer;
  428.     i       : Byte;
  429.     SharedCap : YooHooCapSet;
  430.  
  431.     PROCEDURE TransferNetFiles(Mode: Byte);
  432.     LABEL
  433.       EndWaZoo;
  434.     BEGIN
  435.       SetupTransferWindows(False);
  436.       fsent:=0;
  437.       IF IsCaller THEN
  438.       BEGIN
  439.         IF (CurrentEvent.typ AND etNosend)=etNoSend THEN
  440.         BEGIN
  441.           CASE Mode OF
  442.             1 : ZModemSend('', '', - 2, 8192);
  443.             2 : SendFile('','',SEALink);
  444.             3 : SendFile('','',TeLink);
  445.           END;
  446.         END ELSE
  447.         BEGIN
  448.           IF NOT SendWaZOO(Mode) THEN GOTO EndWaZoo;
  449.         END;
  450.         IF NOT ComPort^.Carrier THEN GOTO EndWaZoo;
  451.         CASE Mode OF
  452.           1 : IF ZModemReceive(cfg.inbound[GlobNodeStat],True)<>ZTRUE THEN GOTO EndWaZoo;
  453.           2 : IF ReceiveFile(cfg.inbound[GlobNodeStat],'',SEALink)<>0 THEN GOTO EndWaZoo;
  454.           3 : IF ReceiveFile(cfg.inbound[GlobNodeStat],'',TeLink)<>0 THEN GOTO EndWaZoo;
  455.         END;
  456.       END ELSE
  457.       BEGIN
  458.         CASE Mode OF
  459.           1 : ZModemReceive(cfg.inbound[GlobNodeStat],True);
  460.           2 : ReceiveFile(cfg.inbound[GlobNodeStat],'',SEALink);
  461.           3 : ReceiveFile(cfg.inbound[GlobNodeStat],'',TeLink);
  462.         END;
  463.         IF NOT ComPort^.Carrier THEN GOTO EndWaZoo;
  464.         IF (CurrentEvent.typ AND etNoSend)=etNoSend THEN
  465.         BEGIN
  466.           RequestSent:=False;
  467.           CASE Mode OF
  468.             1 : ZModemSend('', '', - 2, 8192);
  469.             2 : SendFile('','',SEALink);
  470.             3 : SendFile('','',TeLink);
  471.           END;
  472.         END ELSE
  473.         BEGIN
  474.           IF NOT SendWaZOO(Mode) THEN GOTO EndWaZoo;
  475.         END;
  476.         IF NOT ComPort^.Carrier THEN GOTO EndWaZoo;
  477.         IF RequestSent THEN
  478.         BEGIN
  479.           CASE Mode OF
  480.             1 : ZModemReceive(Cfg.Inbound[GlobNodeStat], True);
  481.             2 : ReceiveFile(Cfg.Inbound[GlobNodeStat], '', SEALink);
  482.             3 : ReceiveFile(Cfg.Inbound[GlobNodeStat], '', TeLink);
  483.           END;
  484.         END;
  485.       END;
  486. EndWaZoo:
  487.       RemoveTransferWindows;
  488.     END;
  489.  
  490.   BEGIN
  491.     IF IsCaller THEN
  492.       IF NOT CheckPassword(True) THEN GOTO ItsOverAndOut;
  493.     ComPort^.PurgeIn;
  494.     FOR i:=1 TO MaxAddresses DO
  495.       WITH Cfg.Addresses[i] DO
  496.         DeleteFile(MakeReqFileName(Net, Node, GlobNodeStat));
  497.     DeleteFile(HoldFileName(Call,False)+'RSP');
  498.     IF IsCaller THEN Inc(StatRec^.DayStat[0].CallsGood);
  499.     SharedCap:=(Hello.Capabilities * RemHello.Capabilities);
  500.     WaZOO:=True;
  501.     {---------------------------------------------------------------------}
  502.     { NON STANDARD BiModem mail transfer                                  }
  503.     {---------------------------------------------------------------------}
  504. {$IFNDEF OS2}
  505.     IF CanDoBiMail IN SharedCap THEN
  506.     BEGIN
  507.       AddLog(':','Session method: BiMail');
  508.       WAZOOMAX:=8192;
  509.       SetupTransferWindows(false);
  510.       ReqFile:=HoldFileName(Call,False)+'REQ';
  511.       IF IsCaller THEN
  512.       BEGIN
  513.         IF ExistFile(ReqFile) THEN
  514.         BEGIN
  515.           IF WzFReq IN RemHello.Capabilities THEN
  516.           BEGIN
  517.             ZModemSend(ReqFile,'',0,8192);
  518.             DeleteFile(ReqFile);
  519.             Inc(FSent);
  520.           END ELSE
  521.             AddLog(':','File Request declined');
  522.         END;
  523.         IF FSent=0 THEN ZModemSend('','',-2,8192) ELSE ZModemSend('','',-1,8192);
  524.         ZModemReceive(cfg.inbound[GlobNodeStat],True);
  525.       END ELSE
  526.       BEGIN
  527.         ZModemReceive(Cfg.Inbound[GlobNodeStat],True);
  528.         IF ExistFile(ReqFile) THEN
  529.         BEGIN
  530.           IF WzFReq IN RemHello.Capabilities THEN
  531.           BEGIN
  532.             ZModemSend(ReqFile,'',0,8192);
  533.             DeleteFile(ReqFile);
  534.             Inc(FSent);
  535.           END ELSE
  536.             AddLog(':','File Request declined');
  537.         END;
  538.         IF FSent=0 THEN ZModemSend('','',-2,8192) ELSE ZModemSend('','',-1,8192);
  539.       END;
  540.       RemoveTransferWindows;
  541.       DeleteFile(MakeTaskFileName('BIMODEM.PTH'));
  542.       DeleteFile(MakeTaskFileName(PoPBiModemInterComLog));
  543.       IF ((CurrentEvent.typ AND etNoSend) = 0) OR (Cfg.BiMail.NoSendOverride) THEN
  544.         SendWaZoo(0);
  545.       GetDir(0, SaveDir);
  546.       SaveDir:=AddBackSlash(SaveDir);
  547.       WriteBiModemConfig(Cfg.Modem.Commport, ComPort^.GetBaudRate, SaveDir);
  548.       IF ScreenHeight<=LinesForStat THEN IntroWin^.ScrollVert(-1);
  549.       MkDir('BIMAIL.!'+HexB(Cfg.TaskNumber)); InOutRes:=0;
  550.       ChangeDir('BIMAIL.!'+HexB(Cfg.TaskNumber));
  551.       IF IsCaller THEN
  552.         WHILE Not ComPort^.KeyPressed AND ComPort^.Carrier DO
  553.           GiveUpTime;
  554.       NormalCursor;
  555. {     PoPGETMEM(SaveWin,20480);}
  556.       SaveWindow(1,1,ScreenWidth,ScreenHeight,True,SaveWin);
  557.       IF MaxAvail>102400 THEN
  558.       BEGIN
  559.         CASE ExecDos(Cfg.BiMail.BiModemPath+' /C'+MakeTaskFileName(SaveDir+PoPBimodemCfgFileName)+
  560.                    ' /'+MakeTaskFileName(SaveDir+PoPBiModemInterComLog),false,noexecdosproc) of
  561.           -1,
  562.  {        -4 : ShellToDos(Cfg.BiModemPath,' /CPORTAL.BMC /portal.icl',False);}
  563.           -2 : AddLog('!','Serious memory allocation error');
  564.           -3 : BEGIN
  565.                  AddLog('!','Serious memory allocation error - Aborting');
  566.                  Halt(254);
  567.                END;
  568.         END;
  569.       END ELSE
  570.         ShellToDos(Cfg.BiMail.BiModemPath,'/C'+MakeTaskFileName(SaveDir+PoPBimodemCfgFileName)+
  571.                    ' /'+MakeTaskFileName(SaveDir+PoPBiModemInterComLog),False);
  572.       RestoreWindow(1,1,ScreenWidth,ScreenHeight,True,SaveWin);
  573. {     PoPFREEMEM(SaveWin,20480);}
  574.       HiddenCursor;
  575.       InOutRes:=0;
  576.       ChangeDir(SaveDir);
  577.       RmDir('BIMAIL.!'+HexB(Cfg.TaskNumber));
  578.       IF IOResult<>0 THEN AddLog('!', 'Can''t remove BiMail temp directory');
  579.       BiMailPostParse;
  580.       GOTO ItsOverAndOut;
  581.     END;
  582. {$ENDIF}
  583.     {---------------------------------------------------------------------}
  584.     { Here goes the code for Janus (When Wynn Wagner III has finished it) }
  585.     {---------------------------------------------------------------------}
  586.     IF DoesJanus IN SharedCap THEN
  587.     BEGIN
  588.       AddLog(':', 'Session method: Janus');
  589.       SetupTransferWindows(True);
  590.       DoJanus;
  591.       RemoveTransferWindows;
  592.       GOTO ItsOverAndOut;
  593.     END;
  594.     {---------------------------------------------------------------------}
  595.     { This is the normal ZModem mail transfer.                            }
  596.     {---------------------------------------------------------------------}
  597.     IF (ZedZipper IN SharedCap) OR (ZedZapper IN SharedCap) THEN
  598.     BEGIN
  599.       IF ZedZapper IN SharedCap THEN
  600.       BEGIN
  601.         AddLog(':', 'Session method: ZedZap');
  602.         WAZOOMAX:=8192;
  603.       END ELSE
  604.       BEGIN
  605.         AddLog(':', 'Session method: ZedZip');
  606.         WAZOOMAX:=1024;
  607.       END;
  608.  
  609.       IF ComPort^.Carrier THEN TransferNetFiles(1);
  610.       GOTO ItsOverAndOut;
  611.     END;
  612.     WaZoo:=False;
  613.     AddLog('!','No common session protocol');
  614. ItsOverAndOut:
  615.     CloseReqFiles;
  616.     AddLog('*', 'End of mail session');
  617.     RemoveEmptyDir(Call);
  618.     i:=1;
  619.     WHILE (i<=MaxAddresses) AND (RemAkA[i].Zone<>0) DO
  620.     BEGIN
  621.       RemoveEmptyDir(RemAka[i]);
  622.       Inc(i);
  623.     END;
  624.   END;
  625.  
  626.   FUNCTION Cooked(CONST s: STRING): STRING;
  627.   VAR
  628.     ss : STRING;
  629.     i  : Byte;
  630.     Ch : S3;
  631.   BEGIN
  632.     ss:='';
  633.     FOR i:=1 TO Length(s) DO
  634.     BEGIN
  635.       Ch:=s[i];
  636.       IF (Ch='\') OR (Ch=']') OR (Ch='}') THEN
  637.         Ch:=Ch+Ch
  638.       ELSE
  639.         IF (Ch<#32) OR (Ch>#127) THEN Ch:='\'+HexB(Byte(s[i]));
  640.       ss:=ss+Ch;
  641.     END;
  642.     Cooked:=ss;
  643.   END;
  644.  
  645.   FUNCTION UnCook(CONST s:STRING):STRING;
  646.   VAR
  647.     ss:STRING;
  648.     i:Byte;
  649.     ii,Test:Integer;
  650.     Ch:S3;
  651.   BEGIN
  652.     ss:='';
  653.     IF s<>'' THEN
  654.     BEGIN
  655.       i:=0;
  656.       REPEAT
  657.         INC(i);
  658.         IF s[i]='\' THEN
  659.         BEGIN
  660.           IF (i<LENGTH(s)) THEN
  661.           BEGIN
  662.             IF (s[i+1]='\') THEN
  663.             BEGIN
  664.               Ch:='\';
  665.               INC(i);
  666.             END ELSE
  667.             BEGIN
  668.               Val('$'+Copy(s,i+1,2),ii,Test);
  669.               Ch:=Char(ii);
  670.               INC(i,2);
  671.             END;
  672.           END ELSE
  673.             Ch:=s[i];
  674.         END ELSE
  675.           Ch:=s[i];
  676.         ss:=ss+Ch;
  677.       UNTIL i>=LENGTH(s);
  678.     END;
  679.     UnCook:=ss;
  680.   END;
  681.  
  682.   FUNCTION NextWord(BufNum:Integer; VAR BufAdr; VAR i:Integer):STRING;
  683.   VAR
  684.     Buf : ARRAY[1..10240] OF Char Absolute BufAdr;
  685.     ss  : STRING;
  686.   BEGIN
  687.     ss:='';
  688.     INC(i);
  689.     REPEAT
  690.       INC(i);
  691.       ss:=ss+Buf[i];
  692.       IF (Buf[i]='}') THEN
  693.         IF (i<BufNum) AND (Buf[i+1]='}') THEN
  694.         BEGIN
  695.           Inc(i);
  696.           Continue;
  697.         END;
  698.     UNTIL (i>=BufNum) OR (Buf[i]='}');
  699.     Dec(ss[0]);
  700.     NextWord:=Trim(UnCook(ss));
  701.   END;
  702.  
  703.   FUNCTION NextWord2(VAR s: STRING): STRING;
  704.   VAR
  705.     ss:STRING;
  706.     Finished:BOOLEAN;
  707.     i : Integer;
  708.   BEGIN
  709.     ss:='';
  710.     i:=0;
  711.     Finished:=FALSE;
  712.     REPEAT
  713.       INC(i);
  714.       ss:=ss+s[i];
  715.       IF (s[i]=']') THEN
  716.         IF (s[i+1]<>']') THEN Finished:=True ELSE Inc(i);
  717.     UNTIL (i=Length(s)) OR Finished;
  718.     Delete(s,1,i);
  719.     Dec(ss[0]);
  720.     Delete(ss,1,1);
  721.     NextWord2:=Trim(ss);
  722.   END;
  723.  
  724.   FUNCTION SendEMSIData: BOOLEAN;
  725.   LABEL
  726.     TryAgain,Out;
  727.   VAR
  728.     t1,t2 : EventTimer;
  729.     s,ss  : STRING;
  730.     c,tries : Byte;
  731.     BufNum,i:Integer;
  732.     Crc16:Word;
  733.     Buf:^EMSIBUFType;
  734.     Flag:Boolean;
  735.     us : NodeListRecType;
  736.   BEGIN
  737.     SendEMSIData:=FALSE;
  738.     New(Buf);
  739.     IF Not CheckPassword(Not IsCaller) THEN GOTO Out;
  740.     s:='**EMSI_DAT';
  741.     Move(s[1],Buf^[1],10);
  742.     s:='{EMSI}{';
  743.     s:=s+Address2Str(Cfg.Addresses[AkaNum]);
  744.     FOR i:=1 TO MaxAddresses DO
  745.     BEGIN
  746.       IF (Cfg.Addresses[i].Zone<>0) AND (i<>AkaNum) THEN
  747.         s:=s+' '+Address2Str(Cfg.Addresses[i]);
  748.     END;
  749.     s:=s+'}{';
  750.     IF FoundInNodes AND (NodesRec.SessionPwd<>'') THEN s:=s+NodesRec.SessionPwd ELSE s:=s+NodeListEntry.Password;
  751.     IF IsCaller THEN
  752.     BEGIN
  753.       s:=s+'}{8N1,PUA}{';
  754. {$IFNDEF OS2}
  755.       IF CanDoBimail In Hello.Capabilities THEN s:=s+'BIM,';
  756. {$ENDIF}
  757.       IF DoesJanus In Hello.Capabilities THEN s:=s+'JAN,';
  758.       s:=s+'ZAP,ZMO,ARC,XMA';
  759.     END ELSE
  760.     BEGIN
  761.       s:=s+'}{8N1}{';
  762. {$IFNDEF OS2}
  763.       IF (Cfg.BiMail.BimodemPath<>'') AND (CanDoBiMail IN RemHello.Capabilities) AND
  764.          (CanDoBiMail IN Hello.Capabilities) THEN s:=s+'BIM' ELSE
  765. {$ENDIF}
  766.         IF (DoesJanus IN RemHello.Capabilities) And (DoesJanus IN Hello.Capabilities) THEN s:=s+'JAN' ELSE
  767.           IF ZedZapper IN RemHello.Capabilities THEN s:=s+'ZAP' ELSE
  768.             IF ZedZipper IN RemHello.Capabilities THEN s:=s+'ZMO' ELSE s:=s+'NCP';
  769.       IF NOT (WZFreq IN Hello.Capabilities) THEN s:=s+',HRQ';
  770.     END;
  771.     Move(s[1],Buf^[15],Length(s));
  772.     BufNum:=Length(s)+15;
  773.     s:='}{'+HexB(PoPProductCode)+'}{Portal of Power}{'+Cooked(Ver)+
  774.        '}{The best mailer, at the price of 5 postcards!}';
  775.     IF NOT FindNode(Cfg.Addresses[Cfg.MainAdrNum], us) THEN
  776.     BEGIN
  777.       us.MiscInfo:='-Unpublished-';
  778.       us.PhoneNumber:='-Unpublished-';
  779.     END;
  780.     s:=s+'{IDENT}{['+Cooked(cfg.system)+']['+Cooked(us.MiscInfo)+']['+
  781.        Cooked(Cfg.SysOp)+']['+us.phonenumber+']['+Long2Str(Cfg.Modem.BaudRate)+'][XA]}';
  782.     s:=s+'{TRX#}{['+HexL(NowAsUnixDate)+']}';
  783.     Move(s[1],Buf^[BufNum],Length(s));
  784.     Inc(BufNum, Integer(Length(s)-1));
  785.     s:=HexW(BufNum-14);
  786.     Move(s[1],Buf^[11],4);
  787.     Crc16:=0;
  788.     FOR i:=3 TO BufNum DO
  789.       Crc16:=UpdCRC16(Byte(Buf^[i]),Crc16);
  790.     Crc16:=UpdCRC16(0,Crc16);
  791.     Crc16:=UpdCRC16(0,Crc16);
  792.     Pause(50);
  793.     Tries:=0;
  794.     NewTimerSecs(t1, 60);
  795.     Flag:=FALSE;
  796.     REPEAT
  797.       ComPort^.PurgeIn;
  798.       ComPort^.PurgeOut;
  799. TryAgain:
  800.       FOR i:=1 TO BufNum DO
  801.         ComPort^.WriteByte(Byte(Buf^[i]), False);
  802. {!!!  FPurgeIn;}
  803.       ComPort^.WriteStr(HexW(Crc16)+#13);
  804.       Inc(Tries);
  805.       IF Tries>6 THEN GOTO Out;
  806.       ss:='';
  807.       NewTimerSecs(t2, 20);
  808.       REPEAT
  809.         REPEAT
  810. {         GiveUpTime;}
  811.         UNTIL ComPort^.KeyPressed OR (NOT ComPort^.Carrier) OR TimerExpired(t2) OR TimerExpired(t1);
  812.         IF NOT ComPort^.Carrier OR TimerExpired(t1) THEN GOTO Out;
  813.         IF TimerExpired(t2) THEN
  814.         BEGIN
  815.           AddLog('!','SendEMSI: Timeout') ;
  816.           GOTO TryAgain;
  817.         END;
  818.         IF ComPort^.KeyPressed THEN
  819.         BEGIN
  820.           c:=ComPort^.ReadByte;
  821.           IF c>=32 THEN
  822.           BEGIN
  823.             ss:=ss+Char(c);
  824.             IF Length(ss)>70 THEN Delete(ss,1,50);
  825.             Flag:=(Pos(EMSIACKStr,ss)>0);
  826.           END;
  827.         END;
  828.       UNTIL Flag OR (TimerExpired(t1));
  829.     UNTIL Flag;
  830.     SendEMSIData:=True;
  831. Out:
  832.     Dispose(Buf);
  833.   END;
  834.  
  835.   FUNCTION ReceiveEMSIData: Boolean;
  836.   LABEL
  837.     NoGood,TryAgain,GotRemains,Out;
  838.   VAR
  839.     AkAStr,s,ss,ns:STRING;
  840.     Tries:Byte;
  841.     Buf:^EMSIBufType;
  842.     crc16,pktcrc:WORD;
  843.     x,bufnum,test,i,c : Integer;
  844.     TestAddress: TFidoAddress;
  845.     N : TNodeInfo;
  846.   BEGIN
  847.     New(Buf);
  848.     ReceiveEMSIData:=False;
  849.     Tries:=4;
  850. TryAgain:
  851.     Dec(Tries);
  852. GotRemains:
  853.     IF Tries=0 THEN GOTO Out;
  854.     i:=14;
  855.     bufnum:=0;
  856.     REPEAT
  857.       IF NOT IsCaller THEN ComPort^.WriteStr(EMSIREQStr+#13);
  858.       c:=TimedRead(750);
  859.       IF NOT ComPort^.Carrier THEN GOTO Out;
  860.       IF c<0 THEN
  861.       BEGIN
  862. NoGood:
  863.         ComPort^.PurgeIn;
  864.         ComPort^.WriteStr(EMSINAKStr+#13);
  865.         AddLog('!','GetEMSI: Drats');
  866.         GOTO TryAgain;
  867.       END;
  868.       IF (c>31) AND (c<128) THEN
  869.       BEGIN
  870.         Inc(BufNum);
  871.         buf^[bufnum]:=Char(c);
  872.         Dec(i);
  873.       END;
  874.     UNTIL (i=0);
  875.     Move(Buf^[1],s[1],14);
  876.     s[0]:=#14;
  877.     IF (s=EMSIINQStr) OR (s=EMSIACKStr) THEN GOTO GotRemains;
  878.     Move(buf^[11],s[1],4);
  879.     s[0]:=#4;
  880.     Val('$'+s,i,test);
  881.     test:=i;
  882.     INC(i,4);
  883.     REPEAT
  884.       c:=TimedRead(750);
  885.       IF NOT ComPort^.Carrier THEN GOTO Out;
  886.       IF c<0 THEN GOTO NoGood;
  887.       IF (c>31) AND (c<128) THEN
  888.       BEGIN
  889.         INC(BufNum);
  890.         Buf^[bufnum]:=Char(c);
  891.         Dec(i);
  892.       END;
  893.     UNTIL (i=0);
  894.     s[0]:=#4;
  895.     Move(buf^[bufnum-3],s[1],4);
  896.     Val('$'+s, pktcrc, i);
  897.     IF i<>0 THEN GOTO NoGood;
  898.     crc16:=0;
  899.     FOR i:=3 TO bufnum-4 DO
  900.       crc16:=UpdCRC16(Byte(buf^[i]), Crc16);
  901.     crc16:=UpdCRC16(0,Crc16);
  902.     crc16:=UpdCRC16(0,Crc16);
  903.     IF pktcrc<>crc16 THEN GOTO NoGood;
  904.     ComPort^.WriteStr(EMSIACKStr+EMSIACKStr+#13);
  905.     FillChar(RemHello, SizeOf(RemHello), 0);
  906.     i:=20;
  907.     Dec(BufNum, 4);
  908.     { DECODE ACTUAL EMSI-DATA-PACKET AND CONVERT TO REMHELLO }
  909.     FillChar(RemHello,SizeOf(RemHello),0);
  910.     { Adresses }
  911.     AkAStr:=NextWord(BufNum,Buf^,i)+' ';
  912.     { Password }
  913.     ss:=NextWord(BufNum,Buf^,i);
  914.     IF Length(ss)>8 THEN ss[0]:=#8;
  915.     IF ss<>'' THEN Move(ss[1],RemHello.Password,Length(ss));
  916.     { Decode Addresses - must be here so we have the password.... }
  917.     x:=0;
  918.     REPEAT
  919.       Inc(x);
  920.       ns:=Copy(AkAStr,1,POS(' ',AkAStr)-1);
  921.       Delete(AkAStr, 1, Length(ns)+1);
  922.       GetAdressFromStr(ns, TestAddress);
  923.       IF x=1 THEN
  924.       BEGIN
  925.         RemHello.Address:=TestAddress;
  926.       END ELSE
  927.       BEGIN
  928.         IF FindNodeInfo(N, TestAddress) And (N.SessionPwd<>'') And
  929.            (StUpCase(ss)<>StUpCase(N.SessionPwd)) THEN
  930.         BEGIN
  931.           AddLog('!', 'Password error on AKA ('+Address2Str(TestAddress)+'): (local/remote) '+
  932.                       '"'+StUpCase(N.SessionPwd)+'"/"'+StUpCase(ss)+'"');
  933.           Dec(x);
  934.         END ELSE
  935.           RemAka[x-1]:=TestAddress;
  936.       END;
  937.     UNTIL (AkAStr='') OR (x>MaxAddresses);
  938.     { PickUp Options }
  939.     EMSIData.Options:=NextWord(BufNum,Buf^,i);
  940.     { Capabilities }
  941.     ss:=NextWord(BufNum,Buf^,i);
  942.     IF Pos('BIM',ss)<>0 THEN RemHello.Capabilities:=RemHello.Capabilities+[CanDoBiMail];
  943.     IF Pos('JAN',ss)<>0 THEN RemHello.Capabilities:=RemHello.Capabilities+[DoesJanus];
  944.     IF Pos('ZAP',ss)<>0 THEN RemHello.Capabilities:=RemHello.Capabilities+[ZedZapper];
  945.     IF Pos('ZMO',ss)<>0 THEN RemHello.Capabilities:=RemHello.Capabilities+[ZedZipper];
  946.     IF (Pos('NRQ',ss)= 0) AND (Pos('HRQ',ss)= 0) THEN RemHello.Capabilities:=RemHello.Capabilities+[WzFreq];
  947.     { Product Code }
  948.     ss:=NextWord(BufNum,Buf^,i);
  949.     Val('$'+ss,RemHello.ProductCode,test);
  950.     { Product Name }
  951.     EMSIData.ProdName:=NextWord(BufNum,Buf^,i);
  952.     { Product version }
  953.     ss:=NextWord(BufNum,Buf^,i);
  954.     EMSIData.ProdName:=EMSIData.ProdName+'/'+ss;
  955.     ns:=Copy(ss,1,POS('.',ss)-1);
  956.     Delete(ss,1,Length(ns)+1);
  957.     Val(ns,RemHello.ProductMaj,test);
  958.     ns:='';
  959.     WHILE (Length(ss)>0) And (ss[1] IN ['0'..'9']) DO
  960.     BEGIN
  961.       ns:=ns+ss[1];
  962.       Delete(ss,1,1);
  963.     END;
  964.     Val(ns,RemHello.ProductMin,test);
  965.     { Mail serial number }
  966.     EMSIData.ProdSerial:=NextWord(BufNum,Buf^,i);
  967.     { Skip until IDENT }
  968.     REPEAT
  969.       ss:=NextWord(BufNum,Buf^,i);
  970.     UNTIL (ss='IDENT') Or (i>=BufNum);
  971.     IF ss='IDENT' THEN
  972.     BEGIN
  973.       { System name }
  974.       ss:=NextWord(BufNum,Buf^,i);
  975.       ns:=NextWord2(ss);
  976.       IF Length(ns)>59 THEN ns[0]:=#59;
  977.       Move(ns[1],RemHello.SystemName,Length(ns));
  978.       EMSIData.Location:=NextWord2(ss);
  979.       ns:=NextWord2(ss);  { SysOp }
  980.       IF Length(ns)>19 THEN ns[0]:=#19;
  981.       Move(ns[1],RemHello.SysOp,Length(ns));
  982.       EMSIData.Phone:=NextWord2(ss);
  983.       EMSIData.BaudRate:=NextWord2(ss);
  984.       EMSIData.Flags:=NextWord2(ss);
  985.       { Skip until TRX# }
  986.       REPEAT
  987.         ss:=NextWord(BufNum,Buf^,i);
  988.       UNTIL (ss='TRX#') Or (i>=BufNum);
  989.       IF ss='TRX#' THEN
  990.       BEGIN
  991.         ss:=NextWord(BufNum,Buf^,i);
  992.         EMSIData.Tranx:=NextWord2(ss);
  993.       END;
  994.     END;
  995.     ShowHisData;
  996.     ReceiveEMSIData:=True;
  997. Out:
  998.     Dispose(Buf);
  999.   END;
  1000.  
  1001.   FUNCTION StartMailSession : Boolean;
  1002.   LABEL
  1003.     s1,s2,s4,s5,s6,s7,s8,s9,s10,EoS;
  1004.   VAR
  1005.     x        : Integer;
  1006.     t,
  1007.     FailSafe : EventTimer;
  1008.     Whacks,Ch: Byte;
  1009.     InStr    : String;
  1010.   BEGIN
  1011.     StartMailSession:=False;
  1012.     Pause(150);                   { Wait for MNP garbage to stop }
  1013.     ComPort^.PurgeIn;                     { Throw away any garbage in buffer }
  1014.     ComPort^.PurgeOut;
  1015.     fsent:=0;
  1016.     Whacks:=0;
  1017.     AkaNum:=0;
  1018.     IsCaller:=True;
  1019.     ExtFlags[1]:=' ';
  1020.     RspFile:='';
  1021.     InStr:='';
  1022.     FillChar(EMSIData, SizeOf(EMSIData), 0);
  1023.     FillChar(RemAka, SizeOf(RemAka), 0);
  1024.     REPEAT
  1025.       Pause(100);
  1026.       ComPort^.WriteByte(32, False);
  1027.       ComPort^.WriteByte(Cr, True);              { Wakeup the mailer in other end }
  1028.       IF ComPort^.KeyPressed THEN InStr:=ModemReadStr;
  1029.       Inc(Whacks);
  1030.     UNTIL (InStr<>'') OR (Whacks=15) OR (NOT ComPort^.Carrier);
  1031.     IF Whacks = 15 THEN
  1032.     BEGIN
  1033.       AddLog(':', 'Other end is sleeping....');
  1034.       Exit;
  1035.     END;
  1036.     IF NOT ComPort^.Carrier THEN
  1037.     BEGIN
  1038.       AddLog(':', 'Other end hung up on us!!');
  1039.       Exit;
  1040.     END;
  1041.     MyWin(IntroWin,1, ScreenHeight-1, 80, ScreenHeight, 2,'',False);
  1042.     IntroWin^.wFastText(' Intro: ' + InStr,1,1);
  1043.     ComPort^.PurgeIn; ComPort^.PurgeOut;
  1044. s1:
  1045.     NewTimerSecs(FailSafe, 30);
  1046.     IF Cfg.UseEMSI THEN
  1047.     BEGIN
  1048.       IF NodesRec.UseEMSI='N' THEN GOTO s2;
  1049.     END ELSE
  1050.     BEGIN
  1051.       IF NodesRec.UseEmsi<>'Y' THEN GOTO s2;
  1052.     END;
  1053.     IF Pos(EMSIREQStr, InStr)=0 THEN
  1054.     BEGIN
  1055.       Whacks:=2;
  1056.       REPEAT
  1057.         InStr:='';
  1058.         ComPort^.WriteStr(EMSIINQStr+Char(YooHoo)+Char(TSync));
  1059.         NewTimerSecs(t, 3);
  1060.         REPEAT
  1061.           IF ComPort^.KeyPressed THEN
  1062.           BEGIN
  1063.             Ch:=ComPort^.ReadByte;
  1064.             IF (Ch=67) OR (Ch=NAK) THEN GOTO s4; { Indsat BK'95 }
  1065.             IF (Ch>31) AND (Ch<128) THEN
  1066.             BEGIN
  1067.               InStr:=InStr+Char(Ch);
  1068.               IF Copy(EMSIREQStr,1,Length(InStr))<>InStr THEN InStr:='';
  1069.             END ELSE
  1070.               IF (Ch=YooHoo) OR (Ch=TSync) THEN GOTO s4;
  1071.           END;
  1072.         UNTIL (TimerExpired(t)) OR (InStr=EMSIREQStr);
  1073.         Dec(Whacks);
  1074.       UNTIL (InStr=EMSIREQStr) OR (Whacks=0);
  1075.     END ELSE
  1076.     BEGIN
  1077.       ComPort^.WriteStr(EMSIINQStr+#13);
  1078.       InStr:=EMSIREQStr;
  1079.     END;
  1080.     IF InStr=EMSIREQStr THEN
  1081.     BEGIN
  1082.       FillOutHello;
  1083.       IntroWin^.wFastText(' JoHo',2,1);
  1084.       IF SendEMSIData THEN
  1085.       BEGIN
  1086.         IntroWin^.wFastText('/2U2',2,6);
  1087.         IF ReceiveEMSIData THEN
  1088.         BEGIN
  1089.           StartMailSession:=WaZoo;
  1090.         END;
  1091.       END;
  1092.     END ELSE
  1093.     BEGIN
  1094. s2:
  1095.       IF NOT ComPort^.Carrier THEN GOTO EoS;
  1096.       ComPort^.WriteByte(YooHoo, False);
  1097.       ComPort^.WriteByte(TSync, True);
  1098. s4:
  1099.       x:=TimedRead(900); { Ændret fra 300 til 900 BK'95}
  1100.       IF (x<0) OR NOT ComPort^.Carrier OR TimerExpired(FailSafe) THEN GOTO EoS;
  1101.       CASE x OF
  1102.         Enq : GOTO s8;
  1103.         67  : GOTO s5;
  1104.         Nak : GOTO s6;
  1105.         01  : GOTO s7;
  1106.         ELSE  GOTO s4;
  1107.       END;
  1108. s5:
  1109.       x:=TimedRead(100); { Ændret fra 300 til 100 BK'95}
  1110.       IF x<0 THEN
  1111.       BEGIN
  1112.         StartMailSession:=True;
  1113.         FTSC_Sender(False);
  1114.         GOTO EoS;
  1115.       END;
  1116.       IF TimerExpired(FailSafe) OR NOT ComPort^.Carrier THEN GOTO EoS;
  1117.       CASE x OF
  1118.         Enq : GOTO s8;
  1119.         00,
  1120.         01,
  1121.         67  : BEGIN
  1122.                 StartMailSession:=True;
  1123.                 FTSC_Sender(False);
  1124.                 GOTO EoS;
  1125.               END;
  1126.         Nak : GOTO s6;
  1127.         ELSE  GOTO s4;
  1128.       END;
  1129. s6:
  1130.       x:=TimedRead(300);
  1131.       IF (x<0) OR NOT ComPort^.Carrier OR TimerExpired(FailSafe) THEN GOTO EoS;
  1132.       CASE x OF
  1133.         Enq : GOTO s8;
  1134.         67  : GOTO s5;
  1135.         Nak : BEGIN
  1136.                 StartMailSession:=True;
  1137.                 FTSC_Sender(False);
  1138.                 GOTO EoS;
  1139.               END;
  1140.         01  : GOTO s7;
  1141.         ELSE  GOTO s4;
  1142.       END;
  1143. s7:
  1144.       x:=TimedRead(300);
  1145.       IF (x<0) OR NOT ComPort^.Carrier OR TimerExpired(FailSafe) THEN GOTO EoS;
  1146.       CASE x OF
  1147.         Enq : GOTO s8;
  1148.         67  : GOTO s5;
  1149.         Nak : GOTO s6;
  1150.         01  : GOTO s7;
  1151.         $fe : BEGIN
  1152.                 StartMailSession:=True;
  1153.                 FTSC_Sender(False);
  1154.                 GOTO EoS;
  1155.               END;
  1156.         ELSE  GOTO s4;
  1157.       END;
  1158. s8:
  1159.       IntroWin^.wFastText(' YooHoo',2,1);
  1160.       IF SendHello THEN GOTO s9 ELSE GOTO s2;
  1161. s9:
  1162.       IntroWin^.Select;
  1163.       IntroWin^.wFastText('/2U2',2,8);
  1164.       x:=TimedRead(500);
  1165.       IF (x<0) OR NOT ComPort^.Carrier OR TimerExpired(FailSafe) THEN GOTO s2;
  1166.       IF x=YooHoo THEN GOTO s10 ELSE GOTO s2;
  1167. s10:
  1168.       IF GetHello THEN
  1169.       BEGIN
  1170.         StartMailSession:=WaZoo;
  1171.       END ELSE
  1172.         GOTO s2;
  1173.     END;
  1174. EoS:
  1175.     KillWindow(IntroWin);
  1176.   END;
  1177.  
  1178.   PROCEDURE ReceiveMailSession(InByte: Integer);
  1179.   LABEL
  1180.     v1,v2,v3,v4,v5,v6,EoS;
  1181.   VAR
  1182.     Errors : Byte;
  1183.   BEGIN
  1184.     IsCaller:=False;
  1185.     ExtFlags[1]:='H';
  1186.     RspFile:='';
  1187.     FillChar(EMSIData, SizeOf(EMSIData), 0);
  1188.     FillChar(RemAka,SizeOf(RemAka),0);
  1189.     IF (InByte=0) AND Cfg.UseEMSI THEN
  1190.     BEGIN
  1191.       ComPort^.PurgeOut;
  1192.       ComPort^.WriteStr(EMSIREQStr+#13);
  1193.       IntroWin^.wFastText(' JoHo',2,1);
  1194.       IF ReceiveEMSIData THEN
  1195.       BEGIN
  1196.         FillOutHello;
  1197.         IntroWin^.wFastText('/2U2',2,6);
  1198.         IF SendEMSIData THEN WaZoo ELSE AddLog('!','Failed EMSI Session');
  1199.       END ELSE
  1200.         AddLog('!','Failed EMSI Session');
  1201.     END ELSE
  1202.     BEGIN
  1203.       Errors:=0;
  1204. v1:
  1205.       IF InByte=YooHoo THEN GOTO v3;
  1206. v2:
  1207.       FTSC_Receiver(False);
  1208.       GOTO EoS;
  1209. v3:
  1210.       IntroWin^.wFastText(' YooHoo',2,1);
  1211.       IF GetHello THEN GOTO v4 ELSE
  1212.       BEGIN
  1213.         AddLog('!','Failed ZedZap Session');
  1214.         GOTO EoS;
  1215.       END;
  1216. v4:
  1217.       InByte:=TimedRead(1000);
  1218.       IF InByte<0 THEN GOTO v5;
  1219.       IF InByte=Enq THEN GOTO v6 ELSE GOTO v4;
  1220. v5:
  1221.       ComPort^.PurgeIn;
  1222.       ComPort^.WriteByte(YooHoo, True);
  1223.       INC(Errors);
  1224.       IF Errors>4 THEN
  1225.       BEGIN
  1226.         AddLog('!','Mail session handshake failed');
  1227.         GOTO EoS;
  1228.       END;
  1229.       GOTO v4;
  1230. v6:
  1231.       IF SendHello THEN
  1232.       BEGIN
  1233.         IntroWin^.Select;
  1234.         IntroWin^.wFastText('/2U2',2,8);
  1235.         WaZoo;
  1236.         GOTO EoS;
  1237.       END ELSE
  1238.         IF NOT ComPort^.Carrier THEN GOTO EoS;
  1239.       GOTO v1;
  1240.     END;
  1241. EoS:
  1242.     KillWindow(IntroWin);
  1243.   END;
  1244.  
  1245. END.
  1246.  
  1247.